<template>
  <el-card>
    <template #header>
      <span>广州地铁三维可视化 Demo</span>
    </template>
    <div
      ref="threeBox"
      style="height: 540px; width: 100%; background: #232323"
    ></div>
    <div style="color: #999; font-size: 13px; margin-top: 8px">
      🚇 这是一个最简地铁线路三维动画，可集成更多线路/交互/数据。
    </div>
  </el-card>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount } from "vue";
import * as THREE from "three";

const threeBox = ref(null);

let renderer, scene, camera, controls;
let metroTube, metroCar;
let animateId = null;
let tubeCurve, tubeLength;

onMounted(() => {
  // 场景
  scene = new THREE.Scene();
  scene.background = new THREE.Color(0x232323);

  // 相机
  camera = new THREE.PerspectiveCamera(
    60,
    threeBox.value.clientWidth / 540,
    0.1,
    1000
  );
  camera.position.set(6, 6, 8);
  camera.lookAt(0, 0, 0);

  // 渲染器
  renderer = new THREE.WebGLRenderer({ antialias: true });
  renderer.setSize(threeBox.value.clientWidth, 540);
  threeBox.value.appendChild(renderer.domElement);

  // 轨道曲线路径（你可以改成更复杂的多段轨迹）
  tubeCurve = new THREE.CatmullRomCurve3([
    new THREE.Vector3(-4, 0, -2),
    new THREE.Vector3(-2, 1, 2),
    new THREE.Vector3(0, 0, 4),
    new THREE.Vector3(2, -1, 2),
    new THREE.Vector3(4, 0, -2),
    new THREE.Vector3(7, 0, -2),
    new THREE.Vector3(7, 0, 2),
  ]);
  tubeLength = tubeCurve.getLength(); // 计算轨道总长度

  // 轨道几何
  const tubeGeo = new THREE.TubeGeometry(tubeCurve, 100, 0.11, 16, false);
  const tubeMat = new THREE.MeshStandardMaterial({
    color: 0x00aaff,
    roughness: 0.6,
    metalness: 0.3,
  });
  metroTube = new THREE.Mesh(tubeGeo, tubeMat);
  scene.add(metroTube);

  // 地铁车厢（简单的盒子，可换成复杂模型）
  const carGeo = new THREE.BoxGeometry(0.5, 0.28, 0.28);
  const carMat = new THREE.MeshStandardMaterial({
    color: 0xff3344,
    metalness: 0.5,
  });
  metroCar = new THREE.Mesh(carGeo, carMat);
  scene.add(metroCar);

  // 灯光
  scene.add(new THREE.AmbientLight(0xffffff, 0.5));
  const dirLight = new THREE.DirectionalLight(0xffffff, 1.2);
  dirLight.position.set(7, 10, 8);
  scene.add(dirLight);

  // 坐标轴
  //   scene.add(new THREE.AxesHelper(2));

  animate();
});

onBeforeUnmount(() => {
  cancelAnimationFrame(animateId);
  renderer?.dispose?.();
  scene = null;
  camera = null;
});

let t = 0, //曲线参数（范围 0-1），表示车厢在轨道上的位置比例（0=起点，1=终点）
  speed = 0.01; // t: 轨道参数 0-1, speed：控制车厢移动速度的常量值（单位：参数变化率/帧）
function animate() {
  animateId = requestAnimationFrame(animate);
  t += speed / tubeLength; // 根据速度和轨道长度更新 t,使物理速度恒定（无论轨道长短，实际移动距离/帧 = speed）
  if (t > 1) t = 0;
  // 沿轨道更新小车位置和朝向
  const pos = tubeCurve.getPointAt(t); //根据参数t获取曲线上的三维坐标点
  const tangent = tubeCurve.getTangentAt(t); //根据参数t获取曲线切线向量（表示前进方向）
  metroCar.position.copy(pos); //更新车厢位置
  // 小车始终朝前
  const axis = new THREE.Vector3(0, 1, 0); // Y轴为上
  metroCar.quaternion.setFromUnitVectors(new THREE.Vector3(1, 0, 0), tangent);
  renderer.render(scene, camera);
}
</script>
